/*
 *   Copyright (c) 2011 Hitachi Data Systems, Inc.
 *
 *   Permission is hereby granted to  this software and associated
 *   documentation files (the "Software"), subject to the terms and
 *   conditions of the Sample Source Code License (SSCL) delivered
 *   with this Software. If you do not agree to the terms and
 *   conditions of the SSCL,
 *
 *     (i)  you must close this file and delete all copies of the
 *          Software, and
 *     (ii) any permission to use the Software is expressly denied.
 *
 */

package com.hds.hcp.apihelpers.query.request;

import java.util.ArrayList;

/**
 * This class holds the <code>systemMetadata</code> data for the query request. Specifically, it provides
 * a container for describing the HCP metadata filtering criteria to be applied to the
 * query results for the records to be returned.
 * <p>
 * The class is constructed as a Bean to facilitate utilizing Jackson JSON 
 * serializer to create JSON formatted requests. The Jackson JSON component
 * will interpret the Bean format and generate JSON string for the object when
 * calling the toString method.
 * <p>
 * Any values that are not explicitly set will result in no value included in the
 * JSON output string. If no values are set, it will be considered an empty filter criteria
 * and thus not filtering will be performed.
 * <p>
 * @version 5.0
 */
public class OperationQuerySystemMetadata extends BaseQueryRequest {

	/**
	 * Subclass of SystemMetadata class that is used to specify the <code>changeTime</code> for 
	 * the HCP object/transaction records to be returned.
	 * <p>
	 * The object contains both a start and ending time time-stamp.
	 * <p>
	 * The class is constructed as a Bean to facilitate utilizing Jackson JSON 
	 * parser/serializer to create JSON formatted requests. The Jackson JSON component
	 * will interpret the Bean format and generate JSON string for the object when
	 * calling the toString method.
	 * <p>
	 * Any values that are not explicitly set will result in no value included in the
	 * JSON output string. If no values are set, it will be considered an empty filter criteria
	 * and thus not filtering will be performed.
	 * <p>
	 * @author Clifford Grimm
	 * @version 1.0
	 */
	static public class ChangeTime {
		private Long _start;
		private Long _end;
		
		public Long getStart() {
			return _start;
		}
		
		public Long getEnd() {
			return _end;
		}
		
		public void setStart(Long inStart) {
			_start = inStart;
		}
		
		public void setEnd(Long inEnd) {
			_end = inEnd;
		}
	}
	
	/**
	 * Subclass of SystemMetadata class that is used to specify the <code>directories</code> for 
	 * HCP object/transaction records to be returned.
	 * <p>
	 * The object builds a list of directories to include.
	 * <p>
	 * The class is constructed as a Bean to facilitate utilizing Jackson JSON 
	 * serializer to create JSON formatted requests. The Jackson JSON component
	 * will interpret the Bean format and generate JSON string for the object when
	 * calling the <code>toString</code> method.
	 * <p>
	 * Any values that are not explicitly set will result in no value included in the
	 * JSON output string. If no values are set, it will be considered an empty filter criteria
	 * and thus no filtering will be performed.
	 * <p>
	 * @author Clifford Grimm
	 * @version 1.0
	 */
	static public class Directories {
		private ArrayList<String> _directory;
		
		/**
		 * Remove all directories from the container.
		 * <p>
		 * A subsequent call to <code>getDirectories</code> method will return <code>null</code> value.
		 */
		public void clear() {
			_directory = null;
		}
		
		/**
		 * Add a directory to the container.
		 * <p>
		 * If the directory already exists in the container, it will not be added. 
		 * @param inDirectory directory to add to the container.
		 */
		public void add(String inDirectory) {
			if (null == _directory) {
				_directory = new ArrayList<String>();
			}
			
			if ( ! _directory.contains(inDirectory))
				_directory.add(inDirectory);
		}
		
		/**
		 * Remove a specific directory from the container.
		 * <p>
		 * If the item requested to be removed was the last remaining item in the container, subsequent calls to 
		 * <code>getDirectories</code> method will return <code>null</code>.
		 * 
		 * @param inDirectory Directory to remove from the container.
		 * @return <code>true</code>, if the value was removed; otherwise, <code>false</code>.
		 */
		public Boolean remove(String inDirectory) {
			Boolean retVal = false;
			
			if (null != _directory) {
				retVal = _directory.remove(inDirectory);

				if (_directory.isEmpty()) _directory = null;
			}
			return retVal;
		}
		
		/**
		 * Getter function to return the <code>ArrayList</code> collection of the current set of directories.
		 * <p>
		 * <b><i>NOTE: This method is used by the JSON Serializer to generate the JSON format from the class definition.
		 * If the name is changed, incorrect JSON will be created.</b></i>
		 * @return <code>ArrayList&lt;&gt;<\code> of transactions types, if any set; otherwise <code>null</code>.
		 */
		public ArrayList<String> getDirectory() {
			return _directory;
		}
	}

	/**
	 * Subclass of SystemMetadata class that is used to specify the <code>namespaces</code> for 
	 * HCP object/transaction records to be returned.
	 * <p>
	 * The object builds a list of HCP namespaces to include.
	 * <p>
	 * The class is constructed as a Bean to facilitate utilizing Jackson JSON 
	 * serializer to create JSON formatted requests. The Jackson JSON component
	 * will interpret the Bean format and generate JSON string for the object when
	 * calling the <code>toString</code> method.
	 * <p>
	 * Any values that are not explicitly set will result in no value included in the
	 * JSON output string. If no values are set, it will be considered an empty filter criteria
	 * and thus no filtering will be performed.
	 * <p>
	 * @author Clifford Grimm
	 * @version 1.0
	 */
	static public class Namespaces {
		private ArrayList<String> _namespace;
		
		/**
		 * Remove all namespaces from the container.
		 * <p>
		 * A subsequent call to <code>getNamespaces</code> method will return <code>null</code> value.
		 */
		public void clear() {
			_namespace = null;
		}
		
		/**
		 * Add a namespace to the container.
		 * <p>
		 * If the namespace already exists in the container, it will not be added. 
		 * @param inNamespace Namespace to add to the container.
		 */
		public void add(String inNamespace) {
			if (null == _namespace) {
				_namespace = new ArrayList<String>();
			}
			
			if ( ! _namespace.contains(inNamespace))
				_namespace.add(inNamespace);
		}
		
		/**
		 * Remove a specific namespace from the container.
		 * <p>
		 * If the item requested to be removed was the last remaining item in the container, subsequent calls to 
		 * <code>getNamespaces</code> method will return <code>null</code>.
		 * 
		 * @param inNamespace Namespace to remove from the container.
		 * @return <code>true</code>, if the value was removed; otherwise, <code>false</code>.
		 */
		public Boolean remove(String inNamespace) {
			Boolean retVal = false;
			
			if (null != _namespace) {
				retVal = _namespace.remove(inNamespace);

				if (_namespace.isEmpty()) _namespace = null;
			}
			return retVal;
		}
		
		/**
		 * Getter function to return the <code>ArrayList</code> collection of the current set of namespaces.
		 * <p>
		 * <b><i>NOTE: This method is used by the JSON Serializer to generate the JSON format from the class definition.
		 * If the name is changed, incorrect JSON will be created.</b></i>
		 * @return <code>ArrayList&lt;&gt;<\code> of transactions types, if any set; otherwise <code>null</code>.
		 */
		public ArrayList<String> getNamespace() {
			return _namespace;
		}
	}
	
	/**
	 * Subclass of SystemMetadata class that is used to specify the <code>transactions</code> for 
	 * HCP object/transaction records to be returned.
	 * <p>
	 * The object builds a list of transactions (create, delete, purge) to include.
	 * <p>
	 * The class is constructed as a Bean to facilitate utilizing Jackson JSON 
	 * serializer to create JSON formatted requests. The Jackson JSON component
	 * will interpret the Bean format and generate JSON string for the object when
	 * calling the <code>toString</code> method.
	 * <p>
	 * Any values that are not explicitly set will result in no value included in the
	 * JSON output string. If no values are set, it will be considered an empty filter criteria
	 * and thus no filtering will be performed.
	 * <p>
	 * @author Clifford Grimm
	 * @version 1.0
	 */
	static public class Transactions {
		static public enum TransactionType { create, delete, purge, dispose, prune };

		private ArrayList<TransactionType> _transaction;
		
		/**
		 * Remove all transactions from the container.
		 * <p>
		 * A subsequent call to <code>getTransactions</code> method will return <code>null</code> value.
		 */
		public void clear() {
			_transaction = null;
		}
		
		/**
		 * Add a transaction to the container.
		 * <p>
		 * If the transaction already exists in the container, it will not be added. 
		 * @param inTransaction Enumeration value of the transaction to add to the container.
		 */
		public void add(TransactionType inTransaction) {
			if (null == _transaction) {
				_transaction = new ArrayList<TransactionType>();
			}
			
			if ( ! _transaction.contains(inTransaction))
				_transaction.add(inTransaction);
		}
		
		/**
		 * Remove a specific transaction from the container.
		 * <p>
		 * If the item requested to be removed was the last remaining item in the container, subsequent calls to 
		 * <code>getTransactions</code> method will return <code>null</code>.
		 * 
		 * @param inTransaction Enumeration value of the transaction to remove from the container.
		 * @return <code>true</code>, if the value was removed; otherwise, <code>false</code>.
		 */
		public Boolean remove(String inTransaction) {
			Boolean retVal = false;
			
			if (null != _transaction) {
				retVal = _transaction.remove(inTransaction);

				if (_transaction.isEmpty()) _transaction = null;
			}
			return retVal;
		}
		
		/**
		 * Getter function to return the <code>ArrayList</code> collection of the current set transactions.
		 * <p>
		 * <b><i>NOTE: This method is used by the JSON Serializer to generate the JSON format from the class definition.
		 * If the name is changed, incorrect JSON will be created.</b></i>
		 * @return <code>ArrayList&lt;&gt;<\code> of transactions types, if any set; otherwise <code>null</code>.
		 */
		public ArrayList<TransactionType> getTransaction() {
			return _transaction;
		}
	}
	
	private ChangeTime _changeTime;
	private Directories _directories;
	private Boolean _indexable;
	private Namespaces _namespaces;
	private Transactions _transactions;
	
	// Getter Methods
	public ChangeTime getChangeTime() {
		return _changeTime;
	}
	
	public Directories getDirectories() {
		return _directories;
	}

	public Boolean getIndexable() {
		return _indexable;
	}
	
	public Namespaces getNamespaces() {
		return _namespaces;
	}
	
	public Transactions getTransactions() {
		return _transactions;
	}
	
	// Setter Methods
	public void setChangeTime(ChangeTime inChangeTime) {
		_changeTime = inChangeTime;
	}
	
	public void setDirectories(Directories inDirs) {
		_directories = inDirs;
	}
	
	public void setIndexable(Boolean inIndexable) {
		_indexable = inIndexable;
	}
	
	public void setNamespaces(Namespaces inNamespaces) {
		_namespaces = inNamespaces;
	}
	
	public void setTransactions(Transactions inTransactions) {
		_transactions = inTransactions;
	}
	
	// General utility functions to add individual items to sub-items.

	/**
	 * Add a directory to the internal <code>Directories</code> collection.
	 * <p>
	 * This helper method avoids having to retrieve any existing object
	 * (or create if needed), add the directory, and then re-add the object
	 * back into the SystemMetadata object.
	 */
	public void addDirectory(String inDir) {
		if (null == _directories) {
			_directories = new Directories();
		}
		_directories.add(inDir);
	}

	/**
	 * Add a namespace to the internal <code>Namespaces</code> collection.
	 * <p>
	 * This helper method avoids having to retrieve any existing object
	 * (or create if needed), add the namespace, and then re-add the object
	 * back into the SystemMetadata object.
	 */
	public void addNamespace(String inNamespace) {
		if (null == _namespaces) {
			_namespaces = new Namespaces();
		}
		_namespaces.add(inNamespace);
	}
	
	/**
	 * Add a transaction to the internal <code>Transactions</code> collection.
	 * <p>
	 * This helper method avoids having to retrieve any existing object
	 * (or create if needed), add the transaction, and then re-add the object
	 * back into the SystemMetadata object.
	 */
	public void addTransaction(Transactions.TransactionType inTransaction) {
		if (null == _transactions) {
			_transactions = new Transactions();
		}
		_transactions.add(inTransaction);
	}
}
